package com.example.financeapi.controller;

import com.example.financeapi.config.annotation.PassToken;
import com.example.financeapi.config.redis.DistributedLocker;
import org.redisson.api.RLock;
import org.redisson.api.RReadWriteLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/redisson")
public class RedissonLockTestController {

    @Autowired
    private DistributedLocker distributedLocker;

    @Autowired
    private RedissonClient redissonClient;

    /**
     * 测试redissonTest
     */
    @PassToken
    @RequestMapping("/test")
    public void redissonTest() {
        String key = "redisson_key";
        for (int i = 0; i < 1000; i++) {
            Thread t = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        System.err.println("=============线程开启============" + Thread.currentThread().getName());
                        /*
                         * distributedLocker.lock(key,10L); //直接加锁，获取不到锁则一直等待获取锁
                         * Thread.sleep(100); //获得锁之后可以进行相应的处理
                         * System.err.println("======获得锁后进行相应的操作======"+Thread.
                         * currentThread().getName());
                         * distributedLocker.unlock(key); //解锁
                         * System.err.println("============================="+
                         * Thread.currentThread().getName());
                         */
                        // 尝试获取锁，等待5秒，自己获得锁后一直不解锁则10秒后自动解锁
                        boolean isGetLock = distributedLocker.tryLock(key, TimeUnit.SECONDS, 5, 10);
                        if (isGetLock) {
                            System.out.println("线程:" + Thread.currentThread().getName() + ",获取到了锁");
                            Thread.sleep(100); // 获得锁之后可以进行相应的处理
                            System.err.println("======获得锁后进行相应的操作======" + Thread.currentThread().getName());
                            //distributedLocker.unlock(key);
                            System.err.println("=============================" + Thread.currentThread().getName());
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
            t.start();
        }
    }

    /**
     * testThreadLockTest
     */
    @PassToken
    @RequestMapping("/test2")
    public void testThreadLockTest(){
        String key = "threadLock";
        for (int i=1; i<100; i++){
            new Thread(new Runnable() {
                @Override
                public void run(){
                    RLock lock = distributedLocker.getLock(key);
                    boolean locked = false;
                    try {
                        locked = lock.tryLock(10, TimeUnit.SECONDS);
                        if (locked) {
                            //开始写业务
                            System.out.println(Thread.currentThread().getName() + "锁住了=====>模拟业务耗时开始...");
                            Thread.sleep(10);
                            System.out.println(Thread.currentThread().getName() + "锁住了=====>模拟业务耗时结束...");
                        } else {
                            System.out.println(Thread.currentThread().getName() + "没锁住。。。");
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        if (locked) {
                            System.out.println(Thread.currentThread().getName() + "释放锁");
                            System.out.println();
                            lock.unlock();
                        }
                    }
                }
            }).start();
        }
    }

    /**
     * 读库存
     */
    @PassToken
    @RequestMapping("/readStock")
    public void readStock() {
        String lockKey = "stock_001";
        RReadWriteLock readWriteLock =redissonClient.getReadWriteLock("lockKey");
        RLock readLock =readWriteLock.readLock();


        readLock.lock();

        readLock.unlock();
    }

    /**
     * 更新库存
     */
    @PassToken
    @RequestMapping("/updateStock")
    public void updateStock() {
        String lockKey = "stock_001";
        RReadWriteLock readWriteLock =redissonClient.getReadWriteLock("lockKey");
        RLock writeLock =readWriteLock.writeLock();

        writeLock.lock();

        writeLock.unlock();


    }
}
